import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
from scipy.stats import skew

def create_time_features(df):
    """
    创建时间相关的特征
    """
    df = df.copy()

    # 补充必要的时间字段
    df['Hour'] = df['DATE OCC'].dt.hour
    df['Month'] = df['DATE OCC'].dt.month

    # 创建周期性时间特征
    df['DayOfWeek'] = df['DATE OCC'].dt.dayofweek
    df['WeekOfYear'] = df['DATE OCC'].dt.isocalendar().week
    df['IsWeekend'] = df['DayOfWeek'].isin([5, 6]).astype(int)
    df['IsNight'] = df['Hour'].isin(list(range(22, 24)) + list(range(0, 6))).astype(int)

    # 创建季节特征
    df['Season'] = pd.cut(df['Month'],
                         bins=[0, 3, 6, 9, 12],
                         labels=['Winter', 'Spring', 'Summer', 'Fall'])

    return df

def create_location_features(df):
    """
    创建位置相关的特征
    """
    df = df.copy()

    # 计算每个网格的犯罪密度
    grid_density = df.groupby(['Lat_Grid', 'Lon_Grid']).size().reset_index(name='Grid_Crime_Density')
    df = df.merge(grid_density, on=['Lat_Grid', 'Lon_Grid'])

    # 计算每个区域的犯罪率
    area_density = df.groupby('AREA NAME').size().reset_index(name='Area_Crime_Density')
    df = df.merge(area_density, on='AREA NAME')

    return df

def create_crime_pattern_features(df):
    """
    创建犯罪模式特征
    """
    df = df.copy()

    # 计算每种犯罪类型的频率
    crime_type_freq = df.groupby('Crm Cd Desc').size().reset_index(name='Crime_Type_Frequency')
    df = df.merge(crime_type_freq, on='Crm Cd Desc')

    # 计算每个位置的犯罪类型多样性
    location_crime_diversity = df.groupby(['Lat_Grid', 'Lon_Grid'])['Crm Cd Desc'].nunique().reset_index(name='Location_Crime_Diversity')
    df = df.merge(location_crime_diversity, on=['Lat_Grid', 'Lon_Grid'])

    return df

def create_temporal_patterns(df):
    """
    创建时间模式特征
    """
    df = df.copy()

    # 计算每个时间段的犯罪频率
    hourly_crime_freq = df.groupby('Hour').size().reset_index(name='Hourly_Crime_Freq')
    df = df.merge(hourly_crime_freq, on='Hour')

    # 计算每个月的犯罪频率
    monthly_crime_freq = df.groupby('Month').size().reset_index(name='Monthly_Crime_Freq')
    df = df.merge(monthly_crime_freq, on='Month')

    return df

def scale_features(df, feature_columns):
    """
    特征标准化
    """
    scaler = StandardScaler()
    df[feature_columns] = scaler.fit_transform(df[feature_columns])
    return df

def create_interaction_features(df):
    """
    创建特征交互
    """
    df = df.copy()

    # 时间和位置的交互特征
    df['Time_Location_Risk'] = df['Hour'] * df['Grid_Crime_Density']
    df['Season_Location_Risk'] = df['Season'].astype('category').cat.codes * df['Grid_Crime_Density']

    return df

def prepare_features_for_model(df):
    """
    准备模型训练的特征
    """
    # 选择数值特征
    numeric_features = [
        'LAT', 'LON', 'Hour', 'Grid_Crime_Density', 'Area_Crime_Density',
        'Crime_Type_Frequency', 'Location_Crime_Diversity', 'Hourly_Crime_Freq',
        'Monthly_Crime_Freq', 'Time_Location_Risk'
    ]

    # 选择分类特征（注意：这些编码特征必须在预处理时完成）
    categorical_features = [
        'AREA NAME_encoded', 'Crm Cd Desc_encoded', 'Premis Desc_encoded',
        'TimeOfDay', 'Season', 'DayOfWeek'
    ]

    # 标准化数值特征
    df = scale_features(df, numeric_features)

    # 获取所有特征
    feature_columns = numeric_features + categorical_features

    # 将所有分类特征转换为独热编码
    df = pd.get_dummies(df, columns=categorical_features, drop_first=True)

    # 只返回模型需要的特征列（独热编码后可能有新列，需重新筛选）
    feature_cols = [col for col in df.columns if col in numeric_features or any(cat in col for cat in categorical_features)]
    return df[feature_cols]

if __name__ == "__main__":
    input_path = "data/processed/processed_crime_data.csv"
    output_path = "data/processed/featured_crime_data.csv"

    df = pd.read_csv(input_path)
    df['DATE OCC'] = pd.to_datetime(df['DATE OCC'])

    df = create_time_features(df)
    df = create_location_features(df)
    df = create_crime_pattern_features(df)
    df = create_temporal_patterns(df)
    df = create_interaction_features(df)

    final_features = prepare_features_for_model(df)
    final_features.to_csv(output_path, index=False)

    print("Feature engineering completed successfully!")
